﻿#region Copyright and License Notice
// Copyright (C)2010-2016 - Rob Levine and other contributors
// http://configgen.codeplex.com
// 
// This file is part of ConfigGen.
// 
// ConfigGen is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// ConfigGen is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License and 
// the GNU Lesser General Public License along with ConfigGen.  
// If not, see <http://www.gnu.org/licenses/>
#endregion

using System;
using ConfigGen.Core.SettingsLoader;
using NUnit.Framework;

namespace ConfigGen.Core.Tests.SettingsLoader
{
    [TestFixture]
    public class CellDataParserTests
    {
        [Test]
        public void SetParsingPreferences001_BothArgsNull()
        {
            var itemUnderTest = new CellDataParser();
            Assert.Throws<InvalidOperationException>(() => itemUnderTest.SetParsingPreferences(null, null));
        }

        [Test]
        public void SetParsingPreferences002_BothArgsEqual()
        {
            var itemUnderTest = new CellDataParser();
            Assert.Throws<InvalidOperationException>(() => itemUnderTest.SetParsingPreferences("q", "q"));
        }

        [Test]
        public void EmptyStringValue001_Getter()
        {
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences("e", "n");
            Assert.AreEqual("e", itemUnderTest.EmptyStringValue);
        }

        [Test]
        public void NullValue001_Getter()
        {
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences("e", "n");
            Assert.AreEqual("n", itemUnderTest.NullValue);
        }

        /// <summary>
        /// Asserts that if SetParsingPreferences is not called before GetCellValue, and exception is thrown.
        /// </summary>
        [Test]
        public void GetCellValue_SetParsingPreferencesNotCalledFirst()
        {
            const string testValue = "test";
            var itemUnderTest = new CellDataParser();
            Assert.Throws<InvalidOperationException>(() => itemUnderTest.GetCellValue(testValue));
        }

        /// <summary>
        /// Asserts that a cell's data is returned if it does not match the "empty value" or the "null value"
        /// </summary>
        [Test]
        public void GetCellValue_NormalCellData()
        {
            const string testValue = "test";
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences("[empty]", "[null]");
            var data = itemUnderTest.GetCellValue(testValue);
            Assert.AreEqual(testValue, data);
        }

        /// <summary>
        /// Asserts that if an "empty value" is specified and the cell data matches this, an empty string is returned
        /// </summary>
        [Test]
        public void GetCellValue_EmptyCell_EmptyValueNotNull()
        {
            const string testValue = "[empty]";
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences("[empty]", "[null]");
            var data = itemUnderTest.GetCellValue(testValue);
            Assert.AreEqual(string.Empty, data);
        }

        /// <summary>
        /// Asserts that if the "empty value" is specified as null, and the cell data is null, an empty string is returned
        /// </summary>
        [Test]
        public void GetCellValue_EmptyCell_EmptyValueNull()
        {
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences(null, "[null]");
            var data = itemUnderTest.GetCellValue(null);
            Assert.AreEqual(string.Empty, data);
        }

        /// <summary>
        /// Asserts that if the "null" is specified, and the cell data matches this, a null is returned
        /// </summary>
        [Test]
        public void GetCellValue_NullCell_NullValueNotNull()
        {
            const string testValue = "[null]";
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences("[empty]", "[null]");
            var data = itemUnderTest.GetCellValue(testValue);
            Assert.IsNull(data);
        }

        /// <summary>
        /// Asserts that if the "null value" is specified as null, and the cell data is null, a null is returned. The previous sentence is admittedly a bit "null heavy"! 
        /// </summary>
        [Test]
        public void GetCellValue_NullCell_NullValueNull()
        {
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences("[empty]", null);
            var data = itemUnderTest.GetCellValue(null);
            Assert.IsNull(data);
        }

        /// <summary>
        /// Asserts that an empty string cell data value is treated as a null cell data value
        /// </summary>
        [Test]
        public void GetCellValue_EmptyCell_EmptyStringCellValueCoercedToNull()
        {
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences(null, "[null]");
            var data = itemUnderTest.GetCellValue(string.Empty);
            Assert.AreEqual(string.Empty, data);
        }

        /// <summary>
        /// Asserts that an DBNull cell data value is treated as a null cell data value
        /// </summary>
        [Test]
        public void GetCellValue_EmptyCell_DBNullCellValueCoercedToNull()
        {
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences(null, "[null]");
            var data = itemUnderTest.GetCellValue(DBNull.Value);
            Assert.AreEqual(string.Empty, data);
        }

        /// <summary>
        /// Asserts that if both the "empty string value" and the "null value" are specified as non-zero strings, but a cell value is null,
        /// an exception is thrown as the reader cannot determine how to infer the meaning of a null cell.
        /// </summary>
        [Test]
        public void GetCellValue_BothParsingPrefsSpecified_NullCellValueThrows()
        {
            var itemUnderTest = new CellDataParser();
            itemUnderTest.SetParsingPreferences("[empty]", "[null]");
            Assert.Throws<SpreadsheetDataException>(() => itemUnderTest.GetCellValue(null));

        }
    }
}
